package panda

import (
	"bytes"
	"crypto/tls"
	"encoding/base64"
	"fmt"
	"logger"
	"mime"
	"mime/multipart"
	"net/smtp"
	"net/textproto"
	"os"
	"path/filepath"
	"strings"
)

var _log = logger.GetLogInfo()

type QQMail struct {
	From        string
	To          []string
	Subject     string
	Text        string
	HTML        string
	Images      []string // 内嵌图片路径
	Attachments []string // 文件附件路径
	Username    string
	Password    string
}

func (m *QQMail) Send() error {
	// QQ邮箱SMTP服务器地址
	qqhost := "smtp.qq.com"
	// QQ邮箱SMTP服务器端口
	qqport := 465

	// 邮箱认证
	auth := smtp.PlainAuth("", m.Username, m.Password, qqhost)

	// 创建一个缓冲区，用于存储邮件内容
	var buf bytes.Buffer
	// 创建一个multipart writer，用于创建邮件的各个部分
	writer := multipart.NewWriter(&buf)

	// 邮件头
	headers := make(map[string]string)
	headers["From"] = m.From
	headers["To"] = strings.Join(m.To, ",")
	headers["Subject"] = mime.QEncoding.Encode("utf-8", m.Subject)
	headers["MIME-Version"] = "1.0"
	// 根据是否有附件决定内容类型
	if len(m.Attachments) > 0 {
		headers["Content-Type"] = fmt.Sprintf("multipart/mixed; boundary=\"%s\"", writer.Boundary())
		_log.Println(writer.Boundary())
	} else {
		headers["Content-Type"] = fmt.Sprintf("multipart/related; boundary=\"%s\"", writer.Boundary())
	}

	// 将邮件头写入缓冲区
	for k, v := range headers {
		buf.WriteString(fmt.Sprintf("%s: %s\r\n", k, v))
	}
	buf.WriteString("\r\n")

	// 文本部分
	if m.Text != "" || m.HTML == "" {
		part, _ := writer.CreatePart(textproto.MIMEHeader{
			"Content-Type": []string{"text/plain; charset=utf-8"},
		})
		part.Write([]byte(m.Text))
	}

	// HTML部分
	if m.HTML != "" {
		part, _ := writer.CreatePart(textproto.MIMEHeader{
			"Content-Type": []string{"text/html; charset=utf-8"},
		})
		part.Write([]byte(m.HTML))
		if strings.Contains(m.HTML, "cid:") && m.Images == nil {
			_log.Warn("请检查 HTML 内容是否正确引用图片资源。")
		}
	}

	// 图片附件
	for _, imgPath := range m.Images {
		fileName := filepath.Base(imgPath)
		part, err := writer.CreatePart(textproto.MIMEHeader{
			"Content-Type":              []string{"image/" + strings.TrimPrefix(filepath.Ext(fileName), ".")},
			"Content-Disposition":       []string{fmt.Sprintf("inline; filename=\"%s\"", fileName)},
			"Content-Transfer-Encoding": []string{"base64"},
			"Content-ID":                []string{fmt.Sprintf("<%s>", fileName)},
		})
		if err != nil {
			return err
		}

		imgData, err := os.ReadFile(imgPath)
		if err != nil {
			return err
		}

		encoder := base64.NewEncoder(base64.StdEncoding, part)
		_, err = encoder.Write(imgData)
		if err != nil {
			return err
		}
		encoder.Close()
	}

	// 文件附件处理
	for _, filePath := range m.Attachments {
		fileName := filepath.Base(filePath)
		part, err := writer.CreatePart(textproto.MIMEHeader{
			"Content-Type":              []string{mime.TypeByExtension(filepath.Ext(fileName))},
			"Content-Disposition":       []string{fmt.Sprintf("attachment; filename=\"%s\"", fileName)},
			"Content-Transfer-Encoding": []string{"base64"},
		})
		if err != nil {
			return err
		}

		fileData, err := os.ReadFile(filePath)
		if err != nil {
			return err
		}

		encoder := base64.NewEncoder(base64.StdEncoding, part)
		_, err = encoder.Write(fileData)
		if err != nil {
			return err
		}
		encoder.Close()
	}

	writer.Close()

	// 建立TLS连接
	tlsconfig := &tls.Config{
		InsecureSkipVerify: true,
		ServerName:         qqhost,
	}

	conn, err := tls.Dial("tcp", fmt.Sprintf("%s:%d", qqhost, qqport), tlsconfig)
	if err != nil {
		return err
	}
	defer conn.Close()

	client, err := smtp.NewClient(conn, qqhost)
	if err != nil {
		return err
	}
	defer client.Close()

	if err = client.Auth(auth); err != nil {
		return err
	}

	if err = client.Mail(m.From); err != nil {
		return err
	}

	for _, addr := range m.To {
		if err = client.Rcpt(addr); err != nil {
			return err
		}
	}

	w, err := client.Data()
	if err != nil {
		return err
	}
	defer w.Close()

	_, err = w.Write(buf.Bytes())
	_log.ColorBlue("邮件发送成功！")
	return err
}
